package com.mxprojects.constructors
{
	import com.mxprojects.gui.BaseForumElement;
	import com.mxprojects.gui.Styles;
	import com.mxprojects.io.Config;
	import com.mxprojects.language.Language;
	import com.mxprojects.language.Word;
	
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TextEvent;
	import flash.filters.DropShadowFilter;
	import flash.text.TextFieldAutoSize;
	
	public class PopupWindow extends BaseForumElement
	{				
		public static const ACTION_BUTTON_NAME:String = "actionButton";
		
		private const ROLLUP_BUTTON_GAP:int = 2;
		private const BACKGROUND_NAME:String = "popupBackground";
		private const NAMES_THAT_DISABLE_DRAGGING:Array = new Array("input", "scroller", "disableDragging");
		
		public var titleText:SimpleTextField; //allows us to offset the contents
		
		//set a var that tells us what roll-up state the window is in
		private var rolledUp:Boolean = false;
		private var contentHolder:Sprite;
		private var masker:MovieClip;
		private var popupWidth:int;
		private var popupHeight:int;
		private var extraText:SimpleTextField;
		private var closeButton:CloseButton;
		private var rollUpButton:RollUpButton;
				
		public function PopupWindow(popupWidth:int, popupHeight:int, title:String, cancelFunction:Function, rollUpEnabled:Boolean = true){			
			//set the shared vars
			this.popupWidth = popupWidth;
			this.popupHeight = popupHeight;
			
			//var create the content holder
			contentHolder = new Sprite();
			
			//create the popup and attach it to the stage
			background = createBackground(popupWidth, popupHeight);
			contentHolder.addChild(background);
			
			//make something for content to be attached to
			addChild(contentHolder);
			
			//add a drop shadow
			filters = [new DropShadowFilter(3, 45, 0, .3)];
			
			//put the title on
			titleText = new SimpleTextField("<span class=\"popupTitle\">" + title + "</span>");
			titleText.x = Styles.css.getStyle(".popupTitle").x;
			titleText.y = Styles.css.getStyle(".popupTitle").y;
			addChild(titleText);
			
			//add a close button
			closeButton = new CloseButton();
			closeButton.x = popupWidth - closeButton.width - Config.TEXT_PADDING;
			closeButton.y = Config.TEXT_PADDING;
			closeButton.addEventListener(MouseEvent.CLICK, cancelFunction, false, 0, true);
			addChild(closeButton);
			
			//add a roll-up button
			if(rollUpEnabled){
				rollUpButton = new RollUpButton();
				rollUpButton.x = popupWidth - rollUpButton.width - closeButton.width - Config.TEXT_PADDING - ROLLUP_BUTTON_GAP;
				rollUpButton.y = Config.TEXT_PADDING;
				rollUpButton.addEventListener(MouseEvent.CLICK, roll, false, 0, true);
				addChild(rollUpButton);
				
				//setup double clickin' to open and close
				background.addEventListener(MouseEvent.DOUBLE_CLICK, roll, false, 0, true);
				background.doubleClickEnabled = true;
			}
			
			//work around to get it on the stage
			MXP3.addContent(this);
			stage.addChild(this);
			
			
			//get the mouse location, height of the box and then center the box
			placeWindowOnStage();
			
			//dragger listening
			addEventListener(MouseEvent.MOUSE_DOWN, dragWindow, false, 0, true);
			addEventListener(MouseEvent.MOUSE_UP, stopDragWindow, false, 0, true);
			stage.addEventListener(Event.MOUSE_LEAVE, stopDragWindow, false, 0, true);
			
			//disable the board
			MXP3.disableBoard();
			
			//parse the CSS defaults
			super.init(".popupBackground", 0, false);
		}
		
		private function placeWindowOnStage():void {
			//sets up a nice safe place for the window
			x = Math.round((MXP3.wStage - width) / 2);
			var newY:int = stage.mouseY - height/2;
			if(newY + height > MXP3.hStage){
				y = Math.round(MXP3.hStage - height - Config.TEXT_PADDING);
			}else{
				y = newY;
			}
			
			//make sure it doesn't fly off the stage
			if(y < Config.TEXT_PADDING){
				y = Config.TEXT_PADDING * 2;
			}
		}
		
		public function addContent(content:DisplayObject, ...itemsToPossiblyMove:Array):void {
			contentHolder.addChild(content);
			
			//check to see that we have breathing room
			for(var i:int = 0; i < itemsToPossiblyMove.length; i++){
				//check the items and if the height of the new object overlaps it then move it down
				var displayObject:DisplayObject = itemsToPossiblyMove[i] as DisplayObject;
				
				if(content.y + content.height + Config.TEXT_PADDING >= displayObject.y){
					displayObject.y = content.y + content.height + Config.TEXT_PADDING;
					
					//see if we need to extend the BG
					if(displayObject.y + displayObject.height + Config.TEXT_PADDING > background.height){
						background.height = displayObject.y + displayObject.height + Config.TEXT_PADDING;
					}
					//re-adjust the BG if need be
					DrawBorder.redraw(background, this);
				}
			}
		}
		
		public function removeContent(content:DisplayObject, resize:Boolean = true):void {
			//this should only be called after adding content
			
			//reduce the size of the popup by the height only if it's greater than the start
			if(resize){
				if(popupHeight < background.height){
					background.height -= content.height;
					DrawBorder.redraw(background, this);
				}
			}
			
			contentHolder.removeChild(content);
		}
		
		public function getContent(contentName:String):* {
			return contentHolder.getChildByName(contentName);
		}
		
		public function changeHeight(newHeight:int, moveActionButton:Boolean = true):void {
			//for when we need to change the width or height
			background.height = newHeight;
			
			//loop through the children and if it's an action button then move it
			if(moveActionButton){
				for(var i:int = 0; i < contentHolder.numChildren; i++){
					if(contentHolder.getChildAt(i).name == ACTION_BUTTON_NAME){	
						var actionButton:ButtonLarge = contentHolder.getChildAt(i) as ButtonLarge;
						background.height = newHeight + actionButton.height + Config.TEXT_PADDING;
						actionButton.y = Math.round(background.height - actionButton.height - Config.TEXT_PADDING);
					}
				}
			}

			DrawBorder.redraw(background, this);
		}
		
		public function set title(text:String):void {
			titleText.htmlText = "<span class=\"popupTitle\">" + text + "</span>";
		}
		
		public function extraTitle(textForExtraTitle:String, textListener:Function = null):void {
			//put the title on
			if(extraText == null){
				extraText = new SimpleTextField("<span class=\"popupTitleExtra\">" + textForExtraTitle + "</span>");
				extraText.x = Math.round(titleText.x + titleText.width + Config.TEXT_PADDING);
				extraText.y = Math.round(titleText.y + (titleText.height/2) - (extraText.height/2));
				addChild(extraText);
				
				//if the text has a listener
				if(textListener != null){
					extraText.addEventListener(TextEvent.LINK, textListener, false, 0, true);
				}
			}else{
				extraText.htmlText = "<span class=\"popupTitleExtra\">" + textForExtraTitle + "</span>";
			}
		}
		
		public function removeFromStage(event:MouseEvent = null, showBoard:Boolean = true):void {
			//dragger listening
			removeEventListener(MouseEvent.MOUSE_DOWN, dragWindow);
			removeEventListener(MouseEvent.MOUSE_UP, stopDragWindow);
			stage.removeEventListener(Event.MOUSE_LEAVE, stopDragWindow);
			
			//if a rollup was there
			if(hasEventListener(MouseEvent.DOUBLE_CLICK)){
				removeEventListener(MouseEvent.DOUBLE_CLICK, roll);
			}

			stage.removeChild(this);
			
			if(showBoard){
				MXP3.enableBoard();
			}
		}
		
		public function createActionButton(buttonText:String, buttonAction:Function):ButtonLarge {
			var actionButton:ButtonLarge = new ButtonLarge(buttonText, buttonAction);
			actionButton.x = Math.round(width / 2 - actionButton.width / 2);
			actionButton.y = Math.round(height - actionButton.height - Config.TEXT_PADDING);
			actionButton.name = ACTION_BUTTON_NAME;
			
			addContent(actionButton);
			
			return actionButton;
		}
		
		public function enableActionButton(actionButton:MovieClip, buttonAction:Function):void {
			actionButton.addEventListener(MouseEvent.CLICK, buttonAction, false, 0, true);
			actionButton.alpha = 1;
		}
		
		public function disableActionButton(actionButton:MovieClip, buttonAction:Function):void {
			actionButton.removeEventListener(MouseEvent.CLICK, buttonAction);
			actionButton.alpha = Config.BUTTON_DISABLED_ALPHA;
		}
		
		public function createTextBlock(text:String, closeFunction:Function = null):SimpleTextField {
			//this will put a chunk of text on the window
			var textBlockPadding:int =  int(Styles.css.getStyle(".popupTextBlock").padding);
			
			var textBlock:SimpleTextField = new SimpleTextField("", 2, true, width - (textBlockPadding * 2));
			textBlock.autoSize = TextFieldAutoSize.CENTER;
			
			//if they want a close button
			if(closeFunction != null){
				var close:MovieClip = createActionButton(Language.main(Word.CLOSE), closeFunction);
				textBlock.height = height - (textBlockPadding * 2) - close.height - titleText.height;
			}else{
				textBlock.height = height - (textBlockPadding * 2) - titleText.height;
			}
			textBlock.x = textBlockPadding;
			textBlock.y = textBlockPadding + titleText.height;
			
			//parse the text
			textBlock.htmlText = "<span class=\"popupTextBlock\">" + text + "</span>";

			//add to the popup
			addContent(textBlock);
			
			//return the text block incase we need to use it
			return textBlock;
		}
		
		public function rollUp():void {
			if(rollUpButton != null){
				roll();
			}
		}
		
		private function createBackground(bgWidth:int, bgHeight:int):MovieClip {
			//this will create the background
			var background:MovieClip = new MovieClip();
			background.graphics.beginFill(Styles.colorToUint(".popupBackground"));
			background.graphics.drawRect(0, 0, bgWidth, bgHeight);
			background.graphics.endFill();
			background.name = BACKGROUND_NAME;
			
			return background;
		}	
		
		private function dragWindow(event:MouseEvent):void {
			//drag the window if you can :D
			if(event.target.name == BACKGROUND_NAME || event.target.name == SimpleTextField.ENABLE_DRAGGING){
				startDrag();
				addEventListener(MouseEvent.MOUSE_MOVE, moveWindow);
				
				//put it to the top
				stage.setChildIndex(this, stage.numChildren - 1);
			}
		}
		
		private function moveWindow(event:MouseEvent):void {
			event.updateAfterEvent();
		}
		
		private function stopDragWindow(event:*):void {
			//this works to stop the window from dragging and also for the stage to detect if the mouse left the stage
			stopDrag();
			removeEventListener(MouseEvent.MOUSE_MOVE, moveWindow);
			
			//see if any window element is invisible
			adjustWindow();
		}
		
		private function adjustWindow():void {
			//this will see if any area of the window needs to be brought back to view
			if(x < 0){
				x = 0;
			}
			
			if(y < 0){
				y = 0;
			}
			
			if(x + width > MXP3.wStage){
				x = MXP3.wStage - width;
			}
			
			if(masker == null){
				if(y + height > MXP3.hStage){
					y = MXP3.hStage - height;
				}
			}else{
				if(y + masker.height > MXP3.hStage){
					y = MXP3.hStage - masker.height;
				}
			}
		}
		
		private function roll(event:MouseEvent = null):void {
			if(!rolledUp){
				rollUpButton.rollUp();
				rolledUp = true;
				
				//mask out the window
				masker = new MovieClip();
				masker.graphics.beginFill(0xFFCC00);
				masker.graphics.drawRect(0, 0, background.width, rollUpButton.height + (Config.TEXT_PADDING * 2));
				masker.graphics.endFill();
				addChild(masker);
				
				contentHolder.mask = masker;
				
				DrawBorder.redraw(masker, this);
			}else{
				rollUpButton.rollDown();
				rolledUp = false;
				
				contentHolder.mask = null;
				removeChild(masker);
				masker = null;
				
				DrawBorder.redraw(background, this);
				
				//check to see if it was opened beyond the stage
				if(y > MXP3.hStage - height - Config.TEXT_PADDING){
					y = MXP3.hStage - height - Config.TEXT_PADDING;
				}
			}
			
			//adjust the window just in case
			adjustWindow();
		}
	}
}